package com.piggy.logi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.logi.sys.api.bo.LogiPricePlanQueryBo;
import com.piggy.logi.sys.api.domain.LogiSysUser;
import com.piggy.logi.sys.api.vo.LogiPricePlanExtVo;
import com.piggy.logi.sys.api.vo.LogiSysDeptExtVo;
import com.piggy.logi.sys.bo.*;
import com.piggy.logi.sys.domain.LogiCustomerBook;
import com.piggy.logi.sys.service.ILogiCustomerBookService;
import com.piggy.logi.sys.service.ILogiCustomerService;
import com.piggy.logi.sys.service.ILogiPricePlanService;
import com.piggy.logi.sys.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.piggy.logi.sys.domain.LogiProjectShipLine;
import com.piggy.logi.sys.mapper.LogiProjectShipLineMapper;
import com.piggy.logi.sys.service.ILogiProjectShipLineService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * 项目收发货线路管理Service业务层处理
 *
 * @author piggy
 * @date 2023-08-18
 */
@Slf4j
@Service
public class LogiProjectShipLineServiceImpl extends ServiceImpl<LogiProjectShipLineMapper, LogiProjectShipLine> implements ILogiProjectShipLineService {

    @Resource
    private ILogiCustomerService customerService;

    @Resource
    private ILogiCustomerBookService bookService;

    @Resource
    private ILogiPricePlanService pricePlanService;

    @Override
    public LogiProjectShipLineExtVo queryById(String id, Long deptId){
        LogiProjectShipLineExtVo vo = getVoById(id, LogiProjectShipLineExtVo.class);
        if (ObjectUtil.isEmpty(vo)) {
            return vo;
        }
        return fillData(Lists.newArrayList(vo), deptId).get(0);
    }

    @Override
    public TableDataInfo<LogiProjectShipLineExtVo> queryPageList(LogiProjectShipLineQueryBo bo) {
        PagePlus<LogiProjectShipLine, LogiProjectShipLineExtVo> result = pageVo(PageUtils.buildPagePlus(bo, true), buildQueryWrapper(bo), LogiProjectShipLineExtVo.class);
        result.setRecordsVo(fillData(result.getRecordsVo(), bo.getDeptId()));
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<LogiProjectShipLineExtVo> queryList(LogiProjectShipLineQueryBo bo) {
        return fillData(listVo(buildQueryWrapper(bo), LogiProjectShipLineExtVo.class), bo.getDeptId());
    }

    private LambdaQueryWrapper<LogiProjectShipLine> buildQueryWrapper(LogiProjectShipLineQueryBo bo) {
        LambdaQueryWrapper<LogiProjectShipLine> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(bo.getId()), LogiProjectShipLine::getId, bo.getId());
        lqw.eq(bo.getProjectId() != null, LogiProjectShipLine::getProjectId, bo.getProjectId());
        lqw.eq(bo.getRecvCustomerId() != null, LogiProjectShipLine::getRecvCustomerId, bo.getRecvCustomerId());
        lqw.eq(bo.getSendCustomerId() != null, LogiProjectShipLine::getSendCustomerId, bo.getSendCustomerId());
        lqw.eq(bo.getRecvBookId() != null, LogiProjectShipLine::getRecvBookId, bo.getRecvBookId());
        lqw.eq(bo.getSendBookId() != null, LogiProjectShipLine::getSendBookId, bo.getSendBookId());
        lqw.eq(bo.getPricePlanId() != null, LogiProjectShipLine::getPricePlanId, bo.getPricePlanId());
        lqw.in(CollUtil.isNotEmpty(bo.getProjectIdList()), LogiProjectShipLine::getProjectId, bo.getProjectIdList());
        return lqw;
    }

    public List<LogiProjectShipLineExtVo> fillData(List<LogiProjectShipLineExtVo> extVos, Long deptId) {
        LinkedHashMap<Long,LogiProjectShipLineExtVo> shipLineMap = extVos.stream().collect(LinkedHashMap::new, (m, v) -> m.put(v.getId(), v), LinkedHashMap::putAll);

        List<Long> customerIds = extVos.stream().map(LogiProjectShipLineExtVo::getSendCustomerId).distinct().collect(Collectors.toList());
        customerIds.addAll(extVos.stream().map(LogiProjectShipLineExtVo::getRecvCustomerId).distinct().collect(Collectors.toList()));
        customerIds.add(-1L);

        List<Long> bookIds = extVos.stream().map(LogiProjectShipLineExtVo::getSendBookId).distinct().collect(Collectors.toList());
        bookIds.addAll(extVos.stream().map(LogiProjectShipLineExtVo::getRecvBookId).distinct().collect(Collectors.toList()));
        bookIds.add(-1L);

        List<Long> pricePlanIds = extVos.stream().map(LogiProjectShipLineExtVo::getPricePlanId).distinct().collect(Collectors.toList());
        pricePlanIds.add(-1L);

        List<LogiCustomerExtVo> customerExtVoList = customerService.queryList(new LogiCustomerQueryBo().setCustomerIdList(customerIds));
        List<LogiCustomerBookVo> bookVoList = bookService.queryList(new LogiCustomerBookQueryBo().setIdList(bookIds));
        List<LogiPricePlanExtVo> priceVoList = pricePlanService.queryList((LogiPricePlanQueryBo) new LogiPricePlanQueryBo().setIdList(pricePlanIds).setDeptId(deptId));

        LinkedHashMap<Long,LogiCustomerExtVo> cusMap = customerExtVoList.stream().collect(LinkedHashMap::new, (m, v) -> m.put(ObjectUtil.defaultIfNull(v.getCustomerId(),-1L), v), LinkedHashMap::putAll);
        LinkedHashMap<Long,LogiCustomerBookVo> bookMap = bookVoList.stream().collect(LinkedHashMap::new, (m, v) -> m.put(ObjectUtil.defaultIfNull(v.getId(),-1L), v), LinkedHashMap::putAll);
        LinkedHashMap<Long,LogiPricePlanExtVo> priceMap = priceVoList.stream().collect(LinkedHashMap::new, (m, v) -> {
            if (ObjectUtil.isEmpty(v)) {
                return ;
            }
            m.put(v.getId(),v);
            }, LinkedHashMap::putAll);

        extVos.stream().peek(Any-> {
            shipLineMap.get(Any.getId()).setRecvCustomer(cusMap.get(Any.getRecvCustomerId()));
            shipLineMap.get(Any.getId()).setSendCustomer(cusMap.get(Any.getSendCustomerId()));
            shipLineMap.get(Any.getId()).setRecvBook(bookMap.get(Any.getRecvBookId()));
            shipLineMap.get(Any.getId()).setSendBook(bookMap.get(Any.getSendBookId()));
            shipLineMap.get(Any.getId()).setPricePlan(priceMap.get(Any.getPricePlanId()));
        }).collect(Collectors.toList());

        return Lists.newArrayList(shipLineMap.values());

    }

    @Override
    public Boolean insertByAddBo(LogiProjectShipLineExtEditBo bo) {
        LogiProjectShipLine add = BeanUtil.toBean(bo, LogiProjectShipLine.class);
        validEntityBeforeSave(add);
        boolean ret = save(add);
        if (ObjectUtil.isNotEmpty(bo.getPrice())) {
            bo.getPrice().setProjectId(bo.getProjectId());
            bo.getPrice().setProjectShiplineId(add.getId());
            bo.getPrice().setPlanName(bo.getProjectName()+"-"+add.getId());
            LogiPricePlanExtVo priceVo = pricePlanService.insertByAddBo(bo.getPrice());
            add.setPricePlanId(priceVo.getId());
            updateById(add);
        }
        return ret;
    }

    @Override
    public Boolean updateByEditBo(LogiProjectShipLineExtEditBo bo) {
        if (ObjectUtil.isEmpty(bo.getId())) {
            return insertByAddBo(bo);
        }
        LogiProjectShipLine update = BeanUtil.toBean(bo, LogiProjectShipLine.class);
        validEntityBeforeSave(update);
        boolean ret = updateById(update);
        if (ObjectUtil.isNotEmpty(bo.getPrice())) {
            bo.getPrice().setProjectId(bo.getProjectId());
            bo.getPrice().setProjectShiplineId(update.getId());
            bo.getPrice().setPlanName(bo.getProjectName()+"-"+update.getId());
            pricePlanService.updateByEditBo(bo.getPrice());
        }
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchByAddBo(List<LogiProjectShipLineExtEditBo> boList) {
        if (CollUtil.isEmpty(boList)) {
            return false;
        }

        this.remove(Wrappers.<LogiProjectShipLine>lambdaQuery().eq(LogiProjectShipLine::getProjectId, boList.get(0).getProjectId()));
        List<LogiProjectShipLine> bookList = BeanUtil.copyToList(boList, LogiProjectShipLine.class);
        return this.saveBatch(bookList);
        //boList.forEach(this::insertByAddBo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchByUpdateBo(List<LogiProjectShipLineExtEditBo> boList) {
        if (CollUtil.isEmpty(boList)) {
            return false;
        }

        this.remove(Wrappers.<LogiProjectShipLine>lambdaQuery().eq(LogiProjectShipLine::getProjectId, boList.get(0).getProjectId()));
        return this.saveOrUpdateBatch(BeanUtil.copyToList(boList, LogiProjectShipLine.class));
//        boList.forEach(this::updateByEditBo);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(LogiProjectShipLine entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }
}
